package cn.edu.xust.communication;

import cn.edu.xust.communication.enums.AmmeterReader;
import cn.edu.xust.communication.enums.AmmeterStatusEnum;
import cn.edu.xust.communication.model.Result;
import cn.edu.xust.communication.protocol.Dlt645Frame;
import cn.edu.xust.communication.server.CommonOp;
import cn.edu.xust.communication.server.handler.NettyServerDefaultHandler;
import cn.edu.xust.configuration.exception.Default200Exception;
import cn.edu.xust.configuration.exception.ErrorConstant;
import cn.edu.xust.entity.AmmeterParameterEntity;
import cn.edu.xust.entity.CollectlogEntity;
import cn.edu.xust.entity.DeviceEntity;
import cn.edu.xust.entity.ElecdataEntity;
import cn.edu.xust.service.CollectlogService;
import cn.edu.xust.service.SysUserService;
import cn.edu.xust.util.BeanContext;
import cn.edu.xust.util.GenUtils;
import cn.edu.xust.util.R;
import com.sun.org.apache.bcel.internal.generic.NEW;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Objects;
import java.util.UUID;

/**
 * 支持DLT645-2007协议数据解析的具体实现
 *
 * @author ：huangxin
 * @modified ：
 * @since ：2020/03/19 11:21
 */

@Slf4j
@NoArgsConstructor
@AllArgsConstructor
public class MyAmmeterReader {

    /**
     * 电表端的IP
     */
    private String ammeterChannelIp;
    /**
     * 电表编号
     */
    private String ammeterId;


    //读当前电压
    public Double readCurrentV() throws Default200Exception {
        //发送
        Result result = this.sendCommand(AmmeterReader.MasterRequestFrame.getControlCode(),
                AmmeterReader.MasterRequestFrame.getBaseDataLen(),
                "33 34 34 35");
        //接收结果并解析
        AmmeterParameterEntity ammeterParameter = this.parseAndPersistenceData(result);
        return ammeterParameter.getCurrentAVoltage();
    }

    //读当前电流
    public Double readCurrentI() throws Default200Exception {
        Result result = this.sendCommand(AmmeterReader.MasterRequestFrame.getControlCode(),
                AmmeterReader.MasterRequestFrame.getBaseDataLen(), "33 34 35 35");
        AmmeterParameterEntity ammeterParameter = this.parseAndPersistenceData(result);
        return ammeterParameter.getCurrentACurrent();
    }


    //读当前电量
    public Double readCurrentPower(DeviceEntity deviceEntity) throws Default200Exception {
        Result result = this.sendCommand(AmmeterReader.MasterRequestFrame.getControlCode(),
                AmmeterReader.MasterRequestFrame.getBaseDataLen(), "33 33 33 33");

        AmmeterParameterEntity ammeterParameter = this.parseAndPersistenceData(result);

        if (result.getCode() != 1) {
            CollectlogService collectlogService = BeanContext.getBean("collectlogService");
            //记录查询结果
            CollectlogEntity collectlog = new CollectlogEntity();
            collectlog.setCt(new Date());
            collectlog.setDevicename(deviceEntity.getName());
            collectlog.setHotelid(deviceEntity.getHotelid());
            collectlog.setRoomname(deviceEntity.getRoomname());
            collectlog.setTaskname("读电表");
            collectlog.setState("0");
            collectlog.setMsg(result.getMessage());
            collectlogService.save(collectlog);
        }
        return ammeterParameter.getCurrentTotalActivePower();
    }


    //读当前状态
    public String readState(DeviceEntity deviceEntity) throws Default200Exception {
        Result result = CommonOp.writeCommand(this.ammeterChannelIp, GenUtils.genEleControlCmd(deviceEntity, "state"), UUID.randomUUID().toString());
        return GenUtils.parseExtraEleState(result);
    }


    //综合上述一起读
    public ElecdataEntity readAll(DeviceEntity deviceEntity) throws Default200Exception {

        //先查电量
        Double power = readCurrentPower(deviceEntity);


        //电量都查不到就不用查其他东西耽误时间了 直接返回超时无响应
        if (StringUtils.isEmpty(power)) {
            throw new Default200Exception(ErrorConstant.ele_power_parse_null);
        }

        //再去查其他的
        Double v = readCurrentI();
        Double v1 = readCurrentV();
        String s = readState(deviceEntity);


        //现在可以查其他的了
        ElecdataEntity elecdataEntity = new ElecdataEntity();
        elecdataEntity.setGatewayid(deviceEntity.getGatewayid());
        elecdataEntity.setDeviceid(deviceEntity.getId());
        elecdataEntity.setVoltage(String.valueOf(v1));
        elecdataEntity.setEleccurrent(String.valueOf(v));
        elecdataEntity.setElecwattage(String.valueOf(power));
        elecdataEntity.setDevicename(deviceEntity.getName());
        elecdataEntity.setTimetype("manual-dev");
        elecdataEntity.setState(s);
        elecdataEntity.setCtime(new Date());
        return elecdataEntity;
    }

    /**
     * 解析并持久化数据，之后再将数据返回给调用者
     */
    private AmmeterParameterEntity parseAndPersistenceData(Result result) throws Default200Exception {
        Dlt645Frame frame = new Dlt645Frame();
        if(result.getMessage().length() <= 8 ){
            log.info("响应长度小于8，解析失败:{}",result);
            throw new Default200Exception(ErrorConstant.resp_low_8);
        }
        return frame.analysis(result.getMessage().substring(8));
    }

    public static void main(String[] args) {
        Dlt645Frame frame = new Dlt645Frame();
        AmmeterParameterEntity analysis = frame.analysis("FEFEFEFE680872250003516891083333333333333333F416".substring(8));
        System.out.println(analysis);

    }

    /**
     * 发送指令
     *
     * @param controlCode        控制码
     * @param dataLen            数据长度
     * @param dataIdentification 数据标识
     */
    private Result sendCommand(String controlCode, String dataLen, String dataIdentification) throws Default200Exception {
        //校验参数
        if (StringUtils.isEmpty(controlCode) || StringUtils.isEmpty(dataLen) || StringUtils.isEmpty(dataIdentification)
                || StringUtils.isEmpty(this.ammeterId) || StringUtils.isEmpty(this.ammeterChannelIp)) {
            log.info("gen_err:{}:{}:{}:{}:{}", controlCode, dataLen, dataIdentification, this.ammeterId, this.ammeterChannelIp);
            throw new Default200Exception(ErrorConstant.gen_err);
        }
        //生成指令
        Dlt645Frame frame = new Dlt645Frame(this.ammeterId, controlCode, dataLen, dataIdentification);
        log.info("读电表:生成指令:{}", frame.createFrame());
        //发送指令返回结果
        return CommonOp.writeCommand(this.ammeterChannelIp, frame.createFrame(), UUID.randomUUID().toString());
    }


}
